#include <sys/resource.h>

#include "base/logging.h"
#include "base/get_local_ip.h"
#include "base/config_reader.h"
#include "group_service_handler.h"
#include <unistd.h>

namespace imserver {

int g_shard_id = 0;
std::string g_shard_path = "";

void * StartGroupService(void * data) {
  ConfigReader * cfg = reinterpret_cast<ConfigReader *>(data);
  int port = cfg->GetWithType<int>("group_service", "port", 9004);
  std::string version = cfg->Get("group_service", "version");
  g_shard_id = cfg->GetWithType<int>("group_service", "shard", -1);
  LOG_INFO("StartGroupService --> start. port:" << port << " version:" << version << " shard:" << g_shard_id);

  melon::service::ThriftService<GroupServiceHandler, GroupServiceProcessor> service;
  g_shard_path = "/im/group_service/v" + version + "/shard_" + boost::lexical_cast<std::string>(g_shard_id);
  service.StartRegister("/im/group_service", version, g_shard_id, base::GetLocalIp(), port, 2);
  service.Start(port);
  return NULL;
}

void UseMaxFdLimit() {
  struct rlimit limit;
  if (getrlimit(RLIMIT_NOFILE, &limit) < 0) {
    LOG_WARN("get open file limit eror.");
  } else {
    LOG_INFO("get rlim_cur=" << limit.rlim_cur << " rlim_max=" << limit.rlim_max);
  }

  limit.rlim_cur = limit.rlim_max;
  if (setrlimit(RLIMIT_NOFILE, &limit) < 0) {
    LOG_WARN("set rlim_cur=" << limit.rlim_cur << " rlim_max=" << limit.rlim_max << " err");
  } else {
    LOG_INFO("set rlim_cur=" << limit.rlim_cur << " rlim_max=" << limit.rlim_max << " ok");
  }
}

void UseCore() {
  struct rlimit rlim;
  getrlimit(RLIMIT_CORE, &rlim);
  LOG_INFO("RLIMIT_CORE old rlim_cur:" << rlim.rlim_cur << " rlim_max:" << rlim.rlim_max);
  rlim.rlim_cur = rlim.rlim_max = 1000*1024*1024;
  int res = setrlimit(RLIMIT_CORE, &rlim);
  LOG_INFO("setrlimit res:" << res << " " << strerror(errno));
  getrlimit(RLIMIT_CORE, &rlim);
  LOG_INFO("RLIMIT_CORE new rlim_cur:" << rlim.rlim_cur << " rlim_max:" << rlim.rlim_max);
}

}

int main(int argc, char **argv) {
  using namespace imserver;
  const char * conf_file = "../conf/group_service.conf";
  char opt;
  while ((opt = getopt(argc, argv, "c:")) != -1) {
    switch (opt) {
    case 'c':
      conf_file = optarg;
      break;
    default:
      std::cerr << "Unknown option " << optopt << std::endl;
      return 1;
    }
  }

  ConfigReader cfg(conf_file);
  if (!cfg) {
    std::cerr << "Config file " << conf_file << " read error!" << std::endl;
    return 1;
  }

  LOG_INIT(cfg.Get("log4cplus", "file"), cfg.Get("log4cplus", "level"));
  srand(time(NULL));

  UseMaxFdLimit();
  UseCore();

  pthread_t thread;
  pthread_create(&thread, NULL, StartGroupService, (void*)&cfg);
  pthread_detach(thread);

  while (true) {
    sleep(30);
  }

  return 0;
}
